package com.bearingnavi.android.overlays;

import java.util.ArrayList;
import java.util.List;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Typeface;

import com.bearingnavi.android.util.ClickableLineOverlay;
import com.bearingnavi.android.util.MarshalOverlay;
import com.bearingnavi.android.util.Mathematics;
import com.bearingnavi.android.util.OverlayUtil;
import com.bearingnavi.android.views.RotateView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class BearingOverlay extends Overlay implements MarshalOverlay, ClickableLineOverlay {

	private GeoPoint geoPoint;
	private GeoPoint destGeoPoint;
	private int index;
	private String lineCaption;
	private int LINE_COLOR = Color.YELLOW;
	
	public BearingOverlay() {
		super();
	}
	
	public BearingOverlay(GeoPoint geoPoint, GeoPoint destGeoPoint, int index) {

		this.geoPoint = geoPoint;
		this.destGeoPoint = destGeoPoint;
		this.index = index;
		this.lineCaption = "#"+(index)+", "+
			Mathematics.calculateInitialBearing(geoPoint, destGeoPoint)+"°";
	}
	
	public int getIndex() {
		return index;
	}

	public void draw(Canvas canvas, MapView mapv, boolean shadow) {
		super.draw(canvas, mapv, shadow);

		Paint paint = new Paint();
		paint.setDither(true);
		paint.setColor(LINE_COLOR);
		paint.setStyle(Paint.Style.FILL_AND_STROKE);
		paint.setStrokeJoin(Paint.Join.ROUND);
		paint.setStrokeCap(Paint.Cap.ROUND);
		paint.setStrokeWidth(5);
		
		
	    Paint textPaint = new Paint();
	    textPaint.setColor(Color.WHITE);
	    textPaint.setTextAlign(Paint.Align.CENTER);
	    textPaint.setTextSize(26);
	    textPaint.setTypeface(Typeface.DEFAULT_BOLD);
	    textPaint.setShadowLayer(2, 0, 2, Color.GRAY);
	    
	    Paint bgPaint = new Paint();
	    bgPaint.setColor(Color.BLACK);
	    bgPaint.setStyle(Paint.Style.FILL_AND_STROKE);
	    bgPaint.setAlpha(75);
	    
	    
	    float textWidth= textPaint.measureText(lineCaption);

		Point lastPoint = new Point();
		Point point = new Point();

		Path path = new Path();

		Projection projection = mapv.getProjection();
		projection.toPixels(geoPoint, lastPoint);
		projection.toPixels(destGeoPoint, point);

		path.moveTo(point.x, point.y);
		path.lineTo(lastPoint.x, lastPoint.y);

		canvas.drawPath(path, paint);
		
		canvas.save();
		
		canvas.rotate(RotateView.getInstance().getBearing(), point.x, point.y-20);
		canvas.drawRect(point.x-10-(int)(textWidth/2), point.y-10, point.x+10+(int)(textWidth/2), point.y-50, bgPaint);
		canvas.drawText(lineCaption, point.x, point.y-20, textPaint);
		
		canvas.restore();
	}

	public String marshal() {
		return new StringBuilder()
		.append(geoPoint.getLatitudeE6())
		.append(MarshalOverlay.FIELDS_SEPARATOR)
		.append(geoPoint.getLongitudeE6())
		.append(MarshalOverlay.FIELDS_SEPARATOR)
		.append(destGeoPoint.getLatitudeE6())
		.append(MarshalOverlay.FIELDS_SEPARATOR)
		.append(destGeoPoint.getLongitudeE6())
		.append(MarshalOverlay.FIELDS_SEPARATOR)
		.append(index)
		.append(MarshalOverlay.FIELDS_SEPARATOR)
		.append(lineCaption).toString();
	}

	public void unmarshal(String[] objectFields, boolean createAsSnapshot, MapView mapView) {
		GeoPoint geoPoint = new GeoPoint(
				Integer.parseInt(objectFields[1]),
				Integer.parseInt(objectFields[2]));
		
		
		GeoPoint destGeoPoint = new GeoPoint(
				Integer.parseInt(objectFields[3]),
				Integer.parseInt(objectFields[4]));
		
		this.geoPoint = geoPoint;
		this.destGeoPoint = destGeoPoint;
		this.lineCaption = objectFields[6];
		if (createAsSnapshot) {
			this.index = Integer.parseInt(objectFields[5]);
		} else {
			this.index = OverlayUtil.getNextBearingOverlayIndex(mapView);
			this.lineCaption = this.lineCaption.replace("#"+Integer.parseInt(objectFields[5])+",", "#"+this.index+",");
		}
	}
	
	public GeoPoint getAnimateTo() {
		return geoPoint;
	}

	public GeoPoint getClickablePoint() {
		return geoPoint;
	}
	
	public List<GeoPoint> getLinePoints() {
		List<GeoPoint> geoPoints = new ArrayList<GeoPoint>();
		geoPoints.add(geoPoint);
		geoPoints.add(destGeoPoint);
		return geoPoints;
	}

	public void onChosenEvent(MapView mapView) {
		LINE_COLOR = Color.RED;
	}

	public void onReleaseChosenEvent(MapView mapView) {
		LINE_COLOR = Color.YELLOW;
	}
	
}
